Solutions/Threat Intelligence (NEW)/Analytic Rules/DomainEntity_DnsEvents.yaml (74 lines of code) (raw):

id: 03a8e294-3fc7-4d65-9da2-cff91fb5b6dc name: TI map Domain entity to DnsEvents description: | Identifies a match in DnsEvents from any Domain IOC from TI severity: Medium requiredDataConnectors: - connectorId: DNS dataTypes: - DnsEvents - connectorId: ThreatIntelligence dataTypes: - ThreatIntelligenceIndicator - connectorId: ThreatIntelligenceTaxii dataTypes: - ThreatIntelligenceIndicator - connectorId: MicrosoftDefenderThreatIntelligence dataTypes: - ThreatIntelligenceIndicator queryFrequency: 1h queryPeriod: 14d triggerOperator: gt triggerThreshold: 0 tactics: - CommandAndControl relevantTechniques: - T1071 query: | // Define the lookback periods for time-based filters let dt_lookBack = 1h; // Look back 1 hour for DNS events let ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators // Fetch threat intelligence indicators related to domains let Domain_Indicators = ThreatIntelIndicators // Filter out indicators without domain names | extend IndicatorType = replace(@"\[|\]|\""", "", tostring(split(ObservableKey, ":", 0))) | where isnotempty(IndicatorType) and IndicatorType == "domain-name" | extend DomainName = tolower(ObservableValue) | extend TI_DomainEntity = DomainName | extend TrafficLightProtocolLevel = tostring(parse_json(AdditionalFields).TLPLevel) | extend Url = iff(ObservableKey == "url:value", ObservableValue, "") | where isnotempty(DomainName) | where TimeGenerated >= ago(ioc_lookBack) | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by Id | where IsActive == true and ValidUntil > now() | extend TI_DomainEntity = DomainName; // Create a list of TLDs in our threat feed for later validation let maxListSize = 100000; // Define the maximum allowed size for each list let list_tlds = Domain_Indicators | extend parts = split(DomainName, '.') | extend tld = parts[(array_length(parts)-1)] | extend IndicatorId = tostring(split(Id, "--")[2]) | summarize count() by tostring(tld) | project tld | summarize make_list(tld, maxListSize); // Perform a join between domain indicators and DNS events to identify potential malicious activity Domain_Indicators | project-reorder *, IsActive, Tags, TrafficLightProtocolLevel, DomainName, Type, TI_DomainEntity // Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation | join kind=innerunique ( DnsEvents | where TimeGenerated > ago(dt_lookBack) // Extract domain patterns from syslog message | where isnotempty(Name) | extend parts = split(Name, '.') | extend tld = parts[(array_length(parts)-1)] // Validate parsed domain by checking if the TLD is in the list of TLDs in our threat feed | where tld in~ (list_tlds) | extend DNS_TimeGenerated = TimeGenerated ) on $left.TI_DomainEntity==$right.Name // Filter out DNS events that occurred after the expiration of the corresponding indicator | where DNS_TimeGenerated < ValidUntil // Group the results by IndicatorId and Name, and keep the DNS event with the latest timestamp | summarize DNS_TimeGenerated = arg_max(DNS_TimeGenerated, *) by Id, Name // Select the desired output fields | extend ActivityGroupNames = extract(@"ActivityGroup:(\S+)", 1, tostring(parse_json(Data).labels)) | project DNS_TimeGenerated, Description, ActivityGroupNames, Id, ValidUntil, Confidence, Url, Computer, ClientIP//, Name, QueryType, Type, TI_DomainEntity // Extract hostname and DNS domain from the Computer field | extend HostName = tostring(split(Computer, '.', 0)[0]), DnsDomain = tostring(strcat_array(array_slice(split(Computer, '.'), 1, -1), '.')) // Rename the timestamp field | extend timestamp = DNS_TimeGenerated entityMappings: - entityType: Host fieldMappings: - identifier: FullName columnName: Computer - identifier: HostName columnName: HostName - identifier: DnsDomain columnName: DnsDomain - entityType: IP fieldMappings: - identifier: Address columnName: ClientIP - entityType: URL fieldMappings: - identifier: Url columnName: Url version: 1.4.4 kind: Scheduled